package com.qy.changemachine.api

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.ResponseBody
import retrofit2.Response
import java.io.File
import java.io.InputStream
import java.io.OutputStream

object FileDownloader {

    interface DownloadCallback {
        fun onProgress(bytesRead: Long, contentLength: Long)
        fun onSuccess()
        fun onError(throwable: Throwable)
    }

    fun downloadFile(
        fileUrl: String,
        destinationFile: File,
        callback: DownloadCallback
    ) {
        // 在 IO 线程启动协程
        CoroutineScope(Dispatchers.IO).launch {
            try {
                // 调用 Retrofit 的 suspend 函数
                val response = RetrofitClient.downloadService.downloadFile(fileUrl)

                if (response.isSuccessful) {
                    response.body()?.let { body ->
                        saveFile(body, destinationFile, callback)
                        withContext(Dispatchers.Main) {
                            callback.onSuccess()
                        }
                    }
                } else {
                    withContext(Dispatchers.Main) {
                        callback.onError(Throwable("Failed to download file: ${response.code()}"))
                    }
                }
            } catch (e: Exception) {
                withContext(Dispatchers.Main) {
                    callback.onError(e)
                }
            }
        }
    }

    private fun saveFile(
        body: ResponseBody,
        destinationFile: File,
        callback: DownloadCallback
    ) {
        var inputStream: InputStream? = null
        var outputStream: OutputStream? = null

        try {
            val contentLength = body.contentLength()
            inputStream = body.byteStream()
            outputStream = destinationFile.outputStream()

            val buffer = ByteArray(4096)
            var bytesRead: Int
            var totalBytesRead = 0L

            while (inputStream.read(buffer).also { bytesRead = it } != -1) {
                outputStream.write(buffer, 0, bytesRead)
                totalBytesRead += bytesRead
                callback.onProgress(totalBytesRead, contentLength)
            }

            outputStream.flush()
        } finally {
            inputStream?.close()
            outputStream?.close()
        }
    }
}